package com.liao.seckill.service.impl;

import com.alibaba.fastjson.JSON;
import com.liao.seckill.constant.GoodsConstant;
import com.liao.seckill.constant.OrderConstant;
import com.liao.seckill.dao.GoodsMiaoShaDao;
import com.liao.seckill.dao.MiaoShaOrderDao;
import com.liao.seckill.dao.OrderDao;
import com.liao.seckill.pojo.*;
import com.liao.seckill.service.OrderService;
import com.liao.seckill.vo.ResOrder;
import com.liao.seckill.vo.ResOrderDetail;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Transactional
@Service
public class OrderServiceImpl implements OrderService {

    private final GoodsMiaoShaDao goodsMiaoShaDao;
    private final OrderDao orderDao;
    private final MiaoShaOrderDao miaoShaOrderDao;
    private final StringRedisTemplate redisTemplate;

    public OrderServiceImpl(GoodsMiaoShaDao goodsMiaoShaDao, StringRedisTemplate redisTemplate,
                            AmqpTemplate amqpTemplate, MiaoShaOrderDao miaoShaOrderDao,
                            OrderDao orderDao) {
        this.goodsMiaoShaDao = goodsMiaoShaDao;
        this.redisTemplate = redisTemplate;
        this.miaoShaOrderDao = miaoShaOrderDao;
        this.orderDao = orderDao;
    }

    @Override
    public TbOrderInf findById(String orderId) {
        Optional<TbOrderInf> optionalTbOrderInf = orderDao.findById(orderId);
        if (optionalTbOrderInf.isEmpty()) {
            return null;
        }
        return optionalTbOrderInf.get();
    }

    @Override
    public TbOrderInf findOrderByUserIdAndGoodsId(Integer userId, Integer goodsId) {
        return orderDao.findByUserIdAndGoodsId(userId, goodsId);
    }

    /**
     * 出现并发问题：商品库存变成负数
     * 解决：
     * 1、在方法上面加synchronized，但是吞吐量从1600降成400
     * 2、在sql语句上面加条件判断库存是否大于0，吞吐量在1200左右
     * 3、还是在Controller层查询比较好
     *
     * @param tbGoodsMiaosha 秒杀的商品信息
     * @param userId         用户Id
     */
    @Override
    public TbOrderInf secKill(TbGoodsMiaosha tbGoodsMiaosha, Integer userId) {
//        Optional<TbGoodsMiaosha> op = goodsMiaoShaDao.findById(id);
//        if (op.isEmpty()) {
//            throw new GoodsStockException("商品未找到");
//        }
//        TbGoodsMiaosha tbGoodsMiaosha = op.get();
//        if (tbGoodsMiaosha.getStockCount() <= 0) {
//            throw new GoodsStockException("库存不足");
//        }
        if (stockSub(tbGoodsMiaosha.getGoodsId())) {
            return createOrder(tbGoodsMiaosha, userId);
        } else {
            return null;
        }
    }

    @Override
    public void secKillMQ(Integer goodsId, Integer userId) {
        TbOrderInf tbOrderInf = orderDao.findByUserIdAndGoodsId(userId, goodsId);
        if (tbOrderInf != null) {
            return;
        }
        Optional<TbGoodsMiaosha> tbGoodsMiaoshaOptional = goodsMiaoShaDao.findById(goodsId);
        if (tbGoodsMiaoshaOptional.isEmpty()) {
            return;
        }
        if (stockSub(goodsId)) {
            createOrder(tbGoodsMiaoshaOptional.get(), userId);
        }
    }

    @Override
    public TbMiaoshaOrder findMiaoShaOrderByOrderId(String orderId) {
        return miaoShaOrderDao.findByOrderId(orderId);
    }

    @Override
    public void miaoShaSender(TbGoodsMiaosha tbGoodsMiaosha, TbUser tbUser) {

    }

    private boolean stockSub(Integer id) {
        int i = goodsMiaoShaDao.stockSub(id);
        return i > 0;
    }

    /**
     * 创建普通订单的秒杀订单
     *
     * @return 订单信息
     */
    public TbOrderInf createOrder(TbGoodsMiaosha tbGoodsMiaosha, Integer userId) {
        TbOrderInf tbOrderInf = new TbOrderInf();
        TbMiaoshaOrder tbMiaoshaOrder = new TbMiaoshaOrder();
        String orderId = UUID.randomUUID().toString();

        //订单信息
        tbOrderInf.setId(orderId);
        tbOrderInf.setCreateTime(new Date());
        tbOrderInf.setOrderChannel(1);
        tbOrderInf.setGoodsId(tbGoodsMiaosha.getGoodsId());
        tbOrderInf.setGoodsName(tbGoodsMiaosha.getName());
        tbOrderInf.setOrderNum(1);
        tbOrderInf.setOrderPrice(tbGoodsMiaosha.getPrice());
        tbOrderInf.setOrderStatus(0);
        tbOrderInf.setUserId(userId);
        orderDao.save(tbOrderInf);

        //秒杀订单信息
        tbMiaoshaOrder.setGoodsId(tbGoodsMiaosha.getGoodsId());
        tbMiaoshaOrder.setOrderId(tbOrderInf.getId());
        tbMiaoshaOrder.setUserId(userId);
        miaoShaOrderDao.save(tbMiaoshaOrder);

        //把订单信息保存至reids缓存
        redisTemplate.opsForValue().set(OrderConstant.ORDER_MIAOSHA_KEY_PREFIX + ":" + tbMiaoshaOrder.getId(),
                JSON.toJSONString(tbMiaoshaOrder), OrderConstant.DEFAULT_ORDER_MIAOSHA_EXPIRE, TimeUnit.SECONDS);

        return tbOrderInf;
    }
}
